package controllers

import (
	"github.com/gin-gonic/gin"
	"google.golang.org/grpc/status"
)

/*
 +----------------------------------------------------------------------
 + Title        : BaseController
 + Author       : huwl
 + Version      : 2.0.0
 + Initial-Time : 2020-11-23
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : 基础控制层
 +----------------------------------------------------------------------
*/
type BaseController struct {
}

// 输出参数结构体
type Params struct {
	StatusCode int
	Code       int
	Data       interface{}
	Message    string
}

// 处理接口
type Handler interface {
	parse(params *Params)
}

// 处理函数
type HandleFunc func(*Params)

// 解析
func (f HandleFunc) parse(params *Params) {
	f(params)
}

/**
 * 设置数据,针对不同默认参数设置闭包函数， 这里比较关键，闭包函数=函数+运行环境（可以引用外部函数的变量）
 *
 * @param statusCode int ---------------------------------------------必传
 * @return HandleFunc
 * @author huwl
 */
func (control *BaseController) WithStatusCode(statusCode int) HandleFunc {
	return func(params *Params) {
		params.StatusCode = statusCode
	}
}

/**
 * 设置数据,针对不同默认参数设置闭包函数， 这里比较关键，闭包函数=函数+运行环境（可以引用外部函数的变量）
 *
 * @param code int ---------------------------------------------------必传
 * @return HandleFunc
 * @author huwl
 */
func (control *BaseController) WithCode(code int) HandleFunc {
	return func(params *Params) {
		params.Code = code
	}
}

/**
 * 设置数据,针对不同默认参数设置闭包函数， 这里比较关键，闭包函数=函数+运行环境（可以引用外部函数的变量）
 *
 * @param data interface ---------------------------------------------必传
 * @return HandleFunc
 * @author huwl
 */
func (control *BaseController) WithData(data interface{}) HandleFunc {
	return func(params *Params) {
		params.Data = data
	}
}

/**
 * 设置信息,针对不同默认参数设置闭包函数， 这里比较关键，闭包函数=函数+运行环境（可以引用外部函数的变量）
 *
 * @param message string ---------------------------------------------必传
 * @return HandleFunc
 * @author huwl
 */
func (control *BaseController) WithMessage(message string) HandleFunc {
	return func(params *Params) {
		params.Message = message
	}
}

/**
 * 从gRPC错误中提取纯净消息,针对不同默认参数设置闭包函数， 这里比较关键，闭包函数=函数+运行环境（可以引用外部函数的变量）
 *
 * @param message string ---------------------------------------------必传
 * @return HandleFunc
 * @author huwl
 */
func (control *BaseController) WithGrpcError(err error) HandleFunc {
	return func(params *Params) {
		if st, ok := status.FromError(err); ok {
			// 只返回状态中的消息部分
			params.Message = st.Message()
		} else {
			// 如果不是gRPC错误，返回原始错误
			params.Message = err.Error()
		}
	}
}

/**
 * 成功输出
 *
 * @param ctx *gin.Context -------------------------------------------必传
 * @param params []Handler -------------------------------------------非必传
 * @return Json
 * @author huwl
 */
func (control *BaseController) BaseSuccess(ctx *gin.Context, params ...Handler) {
	result := &Params{
		Code:    200,
		Data:    nil,
		Message: "",
	}

	for _, param := range params {
		param.parse(result)
	}

	ctx.JSON(200, gin.H{
		"code":    result.Code,
		"data":    result.Data,
		"message": result.Message,
	})
}

/**
 * 错误输出
 *
 * @param ctx *gin.Context -------------------------------------------必传
 * @param params []Handler -------------------------------------------非必传
 * @return Json
 * @author huwl
 */
func (control *BaseController) BaseError(ctx *gin.Context, params ...Handler) {
	result := &Params{
		StatusCode: 200,
		Code:       400,
		Data:       nil,
		Message:    "",
	}

	for _, param := range params {
		param.parse(result)
	}

	ctx.JSON(result.StatusCode, gin.H{
		"code":    result.Code,
		"data":    result.Data,
		"message": result.Message,
	})
}
